package com.rockbb.common.utilities.time;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class TimeUtil {
	public static final String FORMAT_DATE = "yyyy-MM-dd";
	public static final String FORMAT_DATETIME = "yyyy-MM-dd HH:mm";

	/**
	 * 使用已知的日期格式, 还原日期字符串至日期对象, 出错则返回空
	 * 
	 * @param strDate
	 * @param format
	 * @return
	 */
	public static Date getDate(String strDate, String format) 
	{
		Date date = null;
		if (strDate != null && strDate.length() > 0 ) 
		{
			try 
			{
				SimpleDateFormat sdf = new SimpleDateFormat(format);
				date = sdf.parse(strDate);
			} 
			catch (Exception ex) {}
		}
		return date;
	}

	/**
	 * Format a date by specifying the format, using default locale
	 * 
	 * @param date
	 * @param format
	 * @return
	 */
	public static String getStr(Date date, String format)
	{
		return getStr(date, format, null);
	}

	/**
	 * Format a date by specifying the format and locale
	 * 
	 * @param date
	 * @param format
	 * @param locale
	 * @return
	 */
	public static String getStr(Date date, String format, Locale locale) 
	{
		if (date != null) 
		{
			SimpleDateFormat dFormat;
			if (locale != null)
				dFormat = new SimpleDateFormat(format, locale);
			else
				dFormat = new SimpleDateFormat(format);

			return dFormat.format(date);
		} 
		else 
		{
			return "";
		}
	}

	/**
	 * Split a date string, and store the year, month and date into an integer array
	 * 
	 * @param yyyyMMdd
	 * @return int[]{year, month, date}
	 */
	public static int[] getYearMonthDay(String yyyyMMdd) 
	{
		SimpleDateFormat sf =new SimpleDateFormat("yyyyMMdd");
		if (!yyyyMMdd.matches("(19|20)\\d\\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])")) {
			yyyyMMdd = sf.format(new Date());
		}
		int[] values = new int[3];
		values[0] = Integer.parseInt(yyyyMMdd.substring(0, 4));
		values[1] = Integer.parseInt(yyyyMMdd.substring(4, 6));
		values[2] = Integer.parseInt(yyyyMMdd.substring(6, 8));
		return values;
	}

	/**
	 * Get the integer array of input date
	 * 
	 * @param date
	 * @return int[]{year, month, date}
	 */
	public static int[] getYearMonthDay(Date date) 
	{
		SimpleDateFormat sf =new SimpleDateFormat("yyyyMMdd");
		String yyyyMMdd = sf.format(date);
		int[] values = new int[3];
		values[0] = Integer.parseInt(yyyyMMdd.substring(0, 4));
		values[1] = Integer.parseInt(yyyyMMdd.substring(4, 6));
		values[2] = Integer.parseInt(yyyyMMdd.substring(6, 8));
		return values;
	}

	/**
	 * Get the integer array of current date
	 * 
	 * @return int[]{year, month, date}
	 */
	public static int[] getYearMonthDay() 
	{
		return getYearMonthDay(new Date());
	}

	/**
	 * Get the hour, minute and second of current time
	 * 
	 * @return int[]{hour, minute, second}
	 */
	public static int[] getHourMinuteSecond(Date date)
	{
		SimpleDateFormat sf =new SimpleDateFormat("HHmmss");
		String yyyyMMdd = sf.format(date);
		int[] values = new int[3];
		values[0] = Integer.parseInt(yyyyMMdd.substring(0, 2));
		values[1] = Integer.parseInt(yyyyMMdd.substring(2, 4));
		values[2] = Integer.parseInt(yyyyMMdd.substring(4, 6));
		return values;
	}

	/**
	 * Get the number of the day in this week, start from 0
	 * 
	 * @param date
	 * @return 
	 */
	public static int getDayInThisWeek(Date date) {
		String[] days = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
		SimpleDateFormat f = new SimpleDateFormat("EEE", Locale.US);
		String weekday = f.format(date);
		for (int i=0; i<days.length; i++) {
			if (days[i].equals(weekday)) return i;
		}
		return 3;
	}

	/**
	 * Return the string array that presents the Monday and Sunday of this week
	 * 
	 * @param yyyyMMdd
	 * @return new String[]{"yyyyMMdd", "yyyyMMdd"}
	 */
	public static String[] getMondaySunday(String yyyyMMdd) 
	{
		SimpleDateFormat sf =new SimpleDateFormat("yyyyMMdd");
		Date today;
		try {
			today = sf.parse(yyyyMMdd);
		} catch(Exception e) {
			today = new Date();
		}
		int week_day = getDayInThisWeek(today);

		Date monday = new Date(today.getTime() - week_day*3600*1000*24);
		Date sunday = new Date(today.getTime() + (7-week_day)*3600*1000*24);
		
		String[] mon_sun = new String[2];
		mon_sun[0] = sf.format(monday);
		mon_sun[1] = sf.format(sunday);
		return mon_sun;
	}

	/**
	 * Return the dates by specifying the offset of input date. Negative number means earlier days
	 * 
	 * @param date
	 * @param amount
	 * @param format
	 * @return formatted dates
	 */
	public static String[] getRelativeDatesInRange(Date date, int amount, String format) 
	{
		int positive = 1;
		if (amount < 0) 
		{
			positive = -1;
			amount = 0 - amount;
		}
		String[] dates = new String[amount];
		SimpleDateFormat sf =new SimpleDateFormat(format);

		long base_timestamp = date.getTime();
		for(int i=0; i<amount; i++) 
		{
			Date current_date = new Date(base_timestamp - 3600L*1000*24*i);
			String date_str = sf.format(current_date);
			int index = i;
			if (positive == -1) 
			{
				index = amount - 1 - index;
			}
			dates[index] = date_str;
		}
		return dates;
	}

	/**
	 * Return the dates by specifying the offset of input date. Negative number means earlier days
	 * 
	 * @param base_date
	 * @param amount
	 * @param format
	 * @return formatted dates
	 */
	public static String[] getRelativeDatesInRange(String base_date, int amount, String format) 
	{
		int positive = 1;
		if (amount < 0) 
		{
			positive = -1;
			amount = 0 - amount;
		}
		String[] dates = new String[amount];
		SimpleDateFormat sf =new SimpleDateFormat(format);
		Date date;
		try 
		{
			date = sf.parse(base_date);
		} 
		catch(Exception e) 
		{
			date = new Date();
		}
		long base_timestamp = date.getTime();
		for(int i=0; i<amount; i++) 
		{
			Date current_date = new Date(base_timestamp + 3600L*1000*24*i*positive);
			String date_str = sf.format(current_date);
			int index = i;
			if (positive == -1) 
			{
				index = amount - 1 - index;
			}
			dates[index] = date_str;
		}
		return dates;
	}

	/**
	 * Get the date of today in other month, the months can be negative
	 * 
	 * @param yyyyMMdd
	 * @param months
	 * @return
	 */
	public static int[] getTodayByMonth(int[] yyyyMMdd, int months) 
	{
		int[] newdate = new int[3];
		int ori_year = yyyyMMdd[0];
		int ori_month = yyyyMMdd[1];
		int ori_day = yyyyMMdd[2];
		
		int years = months / 12;
		int related_months = months % 12;
		ori_year = ori_year + years;

		if (ori_month + related_months < 1) {
			newdate[0] = ori_year - 1;
			newdate[1] = ori_month + 12 + related_months;
		} else if (ori_month + related_months > 12) {
			newdate[0] = ori_year + 1;
			newdate[1] = ori_month - 12 + related_months;
		} else {
			newdate[0] = ori_year;
			newdate[1] = ori_month + related_months;
		}

		int day = getMaxDaysOfaMonth(newdate[0], newdate[1]);
		if (ori_day > day) {
			newdate[2] = day;
		} else {
			newdate[2] = ori_day;
		}
		return newdate;
	}
	
	public static String[] getTodayNextDay(String yyyyMMdd) {
		SimpleDateFormat sf =new SimpleDateFormat("yyyyMMdd");
		Date today;
		try {
			today = sf.parse(yyyyMMdd);
		} catch(Exception e) {
			today = new Date();
		}
		Date morrow = new Date(today.getTime() + 3600L*1000*24);
		String[] today_nextday = new String[2];
		today_nextday[0] = sf.format(today);
		today_nextday[1] = sf.format(morrow);
		return today_nextday;
	}

	/**
	 * 获得某个月的天数
	 * @param year
	 * @param month
	 * @return
	 */
	public static int getMaxDaysOfaMonth(int year,int month) {
		int days = 0;
		if(month!=2) {
			switch(month) {
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:
				days = 31 ;
				break;
			case 4:
			case 6:
			case 9:
			case 11:
				days = 30;
			}
		} else {
			if((year%4==0 && year%100!=0) || year%400==0) days = 29;
			else  days = 28;
		}
		return days;
	}
	
	/**
	 * 获取与今天时间相差n天的String形式时间
	 * */
	public static String getdate(int n,String format){
		java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(format);
		Calendar c = Calendar.getInstance();
		c.setTime(new Date());
		c.add(Calendar.DAY_OF_MONTH,n);
		String d=sdf.format(c.getTime());
		return d;
	}

	// 测试主函数
	public static void main(String[] args) {
		String olddate = "20110431";
		int[] olddate_numbers = getYearMonthDay(olddate);
		for (int i=-40; i<40; i++) {
			int[] newdate = getTodayByMonth(olddate_numbers, i);
			System.out.println(""+newdate[0] +"-"+newdate[1] + "-" + newdate[2]);
		}
		olddate = "2011-04-28";
		String[] dates = getRelativeDatesInRange(olddate, 80, "yyyy-MM-dd");
		for(int i=0; i<dates.length; i++) {
			System.out.println(dates[i]);
		}
		
		System.out.println("--------- " + TimeUtil.getdate(-1, TimeUtil.FORMAT_DATETIME));

	}
}
